#include "LPC11xx.h"
#include "bitops.h"
#include "spi.h"

void spi0_init(void)
{
  //1. 启用IOCON模块时钟
  setbit(LPC_SYSCON->SYSAHBCLKCTRL, 16);
  
  //2. 配置SPI0引脚
  //2.1 将PIO0_6作为SCK0
  setbits(LPC_IOCON->SCK_LOC, 0, 1, 2);
  setbits(LPC_IOCON->PIO0_6, 0, 2, 2);
  
  //2.2 将PIO0_8配置为MISO引脚
  setbits(LPC_IOCON->PIO0_8, 0, 2, 1);
  
  //2.3 将PIO0_9配置为MOSI引脚
  setbits(LPC_IOCON->PIO0_9, 0, 2, 1);

  //3. 启用SPI0控制器时钟
  setbit(LPC_SYSCON->SYSAHBCLKCTRL, 11);
  //4. 启用SPI0的外设时钟，不分频
  LPC_SYSCON->SSP0CLKDIV = 1;
  //5. 禁用SPI0复位信号
  setbit(LPC_SYSCON->PRESETCTRL, 0);
  
  //6. 配置SPI0数据帧格式
  //配置数据帧大小为8bit，SPI帧格式，极性0，相位0
  setbits(LPC_SSP0->CR0, 0, 3, 7);
  setbits(LPC_SSP0->CR0, 4, 5, 0);
  clrbit(LPC_SSP0->CR0, 6);
  clrbit(LPC_SSP0->CR0, 7);
  
  //7. 配置SPI总线时钟
  //RFID模块时钟频率最大为3MHz
  //SPI0的外设时钟频率为48MHz
  //因此需要进行16分频，注意CPSR寄存器中的值只能配置为偶数
  LPC_SSP0->CPSR = 16;
  
  //8. 启用SPI0控制器
  setbit(LPC_SSP0->CR1, 1);
}

void spi1_init(void)
{
  //启用IOCONFIG时钟
  setbit(LPC_SYSCON->SYSAHBCLKCTRL, 16);

  setbits(LPC_IOCON->PIO2_1, 0, 2, 2); //SCK1
  setbits(LPC_IOCON->PIO2_2, 0, 2, 2); //MISO1
  setbits(LPC_IOCON->PIO2_3, 0, 2, 2); //MOSI1
  
  //启用SPI1的时钟
  setbit(LPC_SYSCON->SYSAHBCLKCTRL, 18);
  
  //配置外设时钟频率(不分频)
  LPC_SYSCON->SSP1CLKDIV = 1;
  
  //禁用复位信号
  setbit(LPC_SYSCON->PRESETCTRL, 2);
  
  //配置数据位8bit，SPI帧格式，极性0，相位0
  setbits(LPC_SSP1->CR0, 0, 3, 7);
  setbits(LPC_SSP1->CR0, 4, 5, 0);
  clrbit(LPC_SSP1->CR0, 6);
  clrbit(LPC_SSP1->CR0, 7);
  
  //设置SPI总线频率为4MHz，外设时钟频率为48M，进行12分频
  LPC_SSP1->CPSR = 12;
  
  //启用SPI1控制器
  setbit(LPC_SSP1->CR1, 1);
}

uint8_t spi0_io(uint8_t byte)
{
  //等待发送队列不满
  while(!chkbit(LPC_SSP0->SR, 1));
  //将数据写入发送队列
  LPC_SSP0->DR = byte;
  //等待发送完成
  while(chkbit(LPC_SSP0->SR, 4));
  //等待接收队列不为空
  while(!chkbit(LPC_SSP0->SR, 2));
  //读取接收队列中内容
  byte = LPC_SSP0->DR;
  
  return byte;
}

uint8_t spi1_io(uint8_t byte)
{
  //等待发送队列不满
  while(!chkbit(LPC_SSP1->SR, 1));
  //发送一个字节
  LPC_SSP1->DR = byte;
  //等待发送完成
  while(chkbit(LPC_SSP1->SR, 4));
  //等待接收队列非空
  while(!chkbit(LPC_SSP1->SR, 2));
  //接收一个字节
  byte = LPC_SSP1->DR;
  
  return byte;
}

//发送一个字节，将收到字节丢弃
void spi0_send(uint8_t byte)
{
  spi0_io(byte);
}

void spi1_send(uint8_t byte)
{
  spi1_io(byte);
}

//接收一个字节，发送全0字节
uint8_t spi0_recv(void)
{
  return spi0_io(0);
}

uint8_t spi1_recv(void)
{
  return spi1_io(0);
}
